// GI 全局光照的实现

// Lightmap-Diffuse  -> 可以查看unity 默认的shader 作为参考
// -> LightingLambert_GI 函数 在 Lighting.cginc 中
// 此时定义个自己的cginc文件 -> CGIncludes ->   MyGlobalGIFirst.cginc

Shader "BuiltIn/GI"
{
    Properties
    {

    }
    SubShader
    {
        Tags {"RenderType" = "Opaque"}
        Pass
        {
            Tags {"LightMode" = "ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // 引入变体 -> 因为有对应需要的宏
            #pragma multi_compile_fwdbase  
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #include "Lighting.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal :NORMAL;
                // 当Back GI 或 Realtime GI 开启时则进行定义 (静态或者动态GI的时候)
                #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
                float4 texcoord1 : TEXCOORD1;
                #endif
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float3 worldPos : TEXCOORD0;
                half3 worldNormal : TEXCOORD2;
                #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
                float4 lightmapUV : TEXCOORD1;
                #endif
            };


            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld,v.vertex);
                #if defined(LIGHTMAP_ON) 
                o.lightmapUV.xy = v.texcoord1 * unity_LightmapST.xy + unity_LightmapST.zw;
                #endif

                #if defined(DYNAMICLIGHTMAP_ON)
                o.lightmapUV.zw = v.texcoord1 * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
                #endif
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                
                SurfaceOutput o;
                // UNITY_INITIALIZE_OUTPUT 将类型的参数都初始化为0 (type,name) -> (类型,变量名)
                UNITY_INITIALIZE_OUTPUT(SurfaceOutput,o)
                o.Normal = i.worldNormal;
                o.Albedo = 1;

                UnityGI gi; 
                UNITY_INITIALIZE_OUTPUT(UnityGI,gi)
                gi.light.color = _LightColor0;
                gi.light.dir = _WorldSpaceLightPos0;   // 光照方向
                gi.indirect.diffuse = 0;  //漫反射
                gi.indirect.specular = 0;   // 高光

                UnityGIInput giInput;
                UNITY_INITIALIZE_OUTPUT(UnityGIInput,giInput)
                giInput.light = gi.light;  // 世界光照的颜色
                giInput.worldPos = i.worldPos;  // 当前世界坐标
                giInput.worldViewDir = normalize(_WorldSpaceCameraPos - i.worldPos);    //世界坐标到摄像机位置归一向量
                giInput.atten = 1;  //光照衰减 平行光默认为1
                giInput.ambient = 0; //  周围光照(环境光？)
                #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
                    giInput.lightmapUV = i.lightmapUV; // lightmapUV 只在烘焙的时候使用
                #endif

              
                // GI间接光照计算，数据存储在gi中
                //LightingLambert_GIMy(o,giInput,gi);
                //return fixed4(gi.indirect.diffuse,1);

                //LightingLambert_GIMy 最终调用 -> 所以这里应该是等价的 UnityGI_BaseMy(UnityGIInput data, half occlusion, half3 normalWorld)
                gi = UnityGI_Base(giInput,1,o.Normal);

                fixed4 c = LightingLambert(o,gi);
                return c;
            }
            ENDCG
        }
    }
}
